package com.tanhua.management.service;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.tanhua.common.mapper.ManagerMapper;
import com.tanhua.common.pojo.Manager;
import com.tanhua.management.utils.ManagerThreadLocal;
import com.tanhua.management.vo.ManagerVo;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class ManagerService {

    @Value("${jwt.secret}")
    private String secret;

    @Autowired
    private ManagerMapper managerMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;



    /**
     * 将uuid和验证码存入redis中
     * @param uuid
     * @param code
     */
    public void codePic(String uuid, String code) {
        try {
            String s = redisTemplate.opsForValue().get("UUID_CODE_" + uuid);
            if (StrUtil.isEmpty(s)) {
                redisTemplate.opsForValue().set("UUID_CODE_" + uuid, code, Duration.ofMinutes(3));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取用户的个人信息,直接从本地线程取
     * @return
     */
    public Manager baseInfo() {
        return ManagerThreadLocal.get();
    }

    /**
     * 通过token获取当前用户
     * @param token
     * @return
     */
    public Manager findUserByToken(String token) {
        try {
            //解析token的方法,盐值从配置文件中获取,获取token体
            Map<String, Object> body = Jwts.parser().setSigningKey(secret)//盐值要相同
                    .parseClaimsJws(token).getBody();

            Manager manager = managerMapper.selectById(Long.valueOf(body.get("id").toString()));

            /*String redisKey = "TANHUA_MANAGER_NAME_" + body.get("id").toString();
            if (!redisTemplate.hasKey(redisKey)) {
                redisTemplate.opsForValue().set(redisKey, manager.getUsername(), Duration.ofMinutes(3));
            }*/
            return manager;
        } catch (ExpiredJwtException e) {
            //记录日志token已过期
            log.info("token已经过期！ token = " + token);
        } catch (Exception e) {
            //记录日志token不合法
            log.error("token不合法！ token = " + token, e);
        }
        //无意义只是为了程序通过编译
        return null;
    }

    /**
     * 用户登出,直接从本地线程中删除即可
     */
    public void logOut() {
        ManagerThreadLocal.remove();
    }

    /**
     * 用户登录
     * @param
     * @return
     */
    public String login(String username, String password, String verificationCode, String uuid) {
        try {
            String verificationCodeKey = this.redisTemplate.opsForValue().get("UUID_CODE_" + uuid);
            // 判断验证码是否过期
            if (StringUtils.isNotEmpty(verificationCode)) {
                // 判断验证码是否正确
                if (StrUtil.equals(verificationCode, verificationCodeKey)) {

                    // 删除验证码
                    this.redisTemplate.delete(uuid);

                    // 查询数据库查找对应的username和password
                    QueryWrapper<Manager> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("username", username);
                    queryWrapper.eq("password",password);
                    Manager manager = this.managerMapper.selectOne(queryWrapper);
                    System.out.println("manager = " + manager);
                    // 如果查找到了
                    if (null != manager) {
                        Map<String, Object> map = new HashMap<>();
                        map.put("id", manager.getUid());

                        // 生成token
                        String token = Jwts.builder()
                                .setClaims(map) //payload，存放数据的位置，不能放置敏感数据，如：密码等
                                .signWith(SignatureAlgorithm.HS256, secret) //设置加密方法和加密盐
                                .setExpiration(new DateTime().plusHours(12).toDate()) //设置过期时间，24小时后过期
                                .compact();
                        return token;
                    }

                }
            }
        } catch (Exception e) {
            log.error("登录失败", e);
        }
        return null;
    }
}
